﻿using HCService.MsgHandler;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Reflection.Emit;
using System.Security;
using System.Text;
using System.Threading;

namespace HCService.Client
{
	public class ClientBase
	{
		static readonly int PackSize = 1024;

		Socket clientSocket;
		NetworkStream clientStream;
		protected Pack outPutPack = null;

		byte[] curBuffer = new byte[PackSize * PackSize];
		int curIndex = 0;
		public ClientBase(Socket socket) {
			outPutPack = null;
			this.clientSocket = socket;
			//ReceiveMsg()
			clientStream = new NetworkStream(this.clientSocket);
			ReceiveMsgThead();
		}

		protected void ReceiveMsg()
		{
			//this.clientSocket.BeginReceive(reveivePack.Buffer, reveivePack.CurIndex, reveivePack.ResumeSize, SocketFlags.None, ReceiveMsgCallBack, this);

			this.clientSocket.BeginReceive(curBuffer, curIndex, curBuffer.Length - curIndex, SocketFlags.None, ReceiveMsgCallBack, this);
		}

		protected void ReceiveMsgCallBack(IAsyncResult iar)
		{
			try
			{
				if (!IsConnected()) return;
				int length = this.clientSocket.EndReceive(iar);
				if (length > 0)
				{
					curIndex += length;
					
					while (true)
					{
						if (curIndex >= 4)
						{
							var packSize = BitConverter.ToInt32(curBuffer, 0);
							if (curIndex > (sizeof(int) + packSize))
							{
								var lastTime = DateTime.Now;
								var headSize = BitConverter.ToInt32(curBuffer, 4);
								string tag = Encoding.UTF8.GetString(curBuffer, 2 * sizeof(int), headSize);

								outPutPack = new Pack(packSize - sizeof(int) - headSize);
								outPutPack.HandleTag = tag;
								Array.Copy(curBuffer, 2 * sizeof(int) + headSize, outPutPack.Buffer, 0, outPutPack.Buffer.Length);

								Array.Copy(curBuffer, (sizeof(int) + packSize), curBuffer, 0, curIndex - sizeof(int) - packSize);
								curIndex -= (sizeof(int) + packSize);

							}
							else
								break;
						}
						else
							break;
					}
					ReceiveMsg();
				}
			}
			catch (Exception exp)
			{
				Console.WriteLine($"Client Recevie Msg Exceotion {exp.StackTrace}");
			}
		}

		protected bool IsConnected()
		{
			return null != clientSocket && clientSocket.Connected;
		}
		
		protected void ReceiveMsgThead()
		{
			Thread thread = new Thread(InterReceiveMsgThread);
			thread.Name = this.clientSocket.RemoteEndPoint.ToString();
			thread.IsBackground = true;
			thread.Start(clientStream);
		}

		protected void InterReceiveMsgThread(object o)
		{
			var skStream = o as NetworkStream;
			while (IsConnected())
			{
				Console.WriteLine($"{skStream.Read(curBuffer, 0, curBuffer.Length).ToString()}");
				Thread.Sleep(10);
			}
		}
	}
}
